package com.fowo.api.service.handleWork;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fowo.api.common.excel.TemplateModelBuildEventListener;
import com.fowo.api.common.model.ImportRow;
import com.fowo.api.common.util.SheetUtils;
import com.fowo.api.entity.ListingFather;
import com.fowo.api.entity.Product;
import com.fowo.api.entity.ShopInfo;
import com.fowo.api.mapper.ListingFatherMapper;
import com.fowo.api.model.listing.father.*;
import com.fowo.api.service.ShopInfoService;
import com.fowo.api.service.impl.ProductServiceImpl;
import com.fowo.api.service.impl.ShopInfoServiceImpl;
import com.fowo.api.service.impl.SysRegionServiceImpl;
import com.fowo.api.syncAmazon.service.impl.TmpSyncListingServiceImpl;
import com.fowo.api.sys.annotation.DataActivity;
import com.fowo.api.sys.entity.SysFile;
import com.fowo.api.sys.entity.SysUser;
import com.fowo.api.sys.entity.enums.SysDataActivityAction;
import com.fowo.api.sys.service.FileService;
import com.fowo.api.sys.service.SysUserService;
import com.fowo.api.sys.service.impl.SysUserServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;

@Service
@Slf4j
public class ListingDService extends ServiceImpl<ListingFatherMapper, ListingFather> {
    @Resource
    private ProductServiceImpl productService;
    @Resource
    private FileService fileService;
    @Resource
    protected Validator validator;
    @Resource
    private SysUserServiceImpl sysUserService;
    @Resource
    private ShopInfoServiceImpl shopInfoService;
    @Resource
    private TmpSyncListingServiceImpl tmpSyncListingService;
    @Resource
    private SysRegionServiceImpl sysRegionService;


    /**
     * 手动配对
     *
     * @param param
     * @return
     */
    @DataActivity(
            action = SysDataActivityAction.Other,
            message = "%s执行了配对操作"
    )
    public boolean pair(ListingBatchPairBo param) {
        Product product = productService.getById(param.getProductId());

        List<ListingFather> listingFathers = new ArrayList<>();
        for (Long listingId : param.getListingIds()) {
            ListingFather listingFather = this.getById(listingId);

            listingFather.setPairProduct(product.getId());
            listingFather.setProductName(product.getName());
            listingFather.setSku(product.getSku());
            listingFather.setClassify(product.getClassify());
            listingFather.setBrand(product.getBrand());
            listingFather.setPairStatus("1");
            listingFather.setPairUpdateTime(new Date());
            listingFather.setPairType("1");
            listingFathers.add(listingFather);

        }
        this.updateBatchById(listingFathers);
        if (param.getIsSync()) {
            product.setPicUrl(listingFathers.get(0).getImg());
            productService.updateById(product);
        }
        return true;
    }

    /**
     * 导入配对
     *
     * @param sysFile
     * @return
     * @throws Exception
     */
    @DataActivity(
            action = SysDataActivityAction.Other,
            message = "%s执行了导入配对操作"
    )
    public boolean uploadPair(SysFile sysFile) throws Exception {
//        SysFile sysFile = fileService.upload(file, null);
        try (InputStream in = fileService.read(sysFile)) {
            List<ImportRow<ListingPairBo>> rows = new ArrayList<>();
            List<ListingPairBo> list = new ArrayList<>();

            // 读取 Excel 到 rows
            EasyExcel
                    .read(in)
                    .useDefaultListener(false)
                    .registerReadListener(
                            new TemplateModelBuildEventListener<>(ListingPairBo.class, null) {
                                @Override
                                public void invokeRow(ListingPairBo row, AnalysisContext cxt) {
                                    ListingPairBo vo = new ListingPairBo();
                                    ImportRow<ListingPairBo> ir = excelToImportRow(row, cxt.readRowHolder().getRowIndex(), vo);
                                    if (ir.isEmptyRow()) {
                                        return;
                                    }
                                    rows.add(ir);
                                    list.add(vo);
                                }
                            }
                    )
                    .sheet()
                    .doRead();

            return batchPair(list);
        }
    }

    /**
     * 导入单行处理
     *
     * @param row       要导入的行
     * @param rowNumber 所在行号
     * @param vo        输出VO,可空
     * @return 导入行对象
     */
    protected ImportRow<ListingPairBo> excelToImportRow(ListingPairBo row, Integer rowNumber, ListingPairBo vo) {
        ImportRow<ListingPairBo> ir = new ImportRow<ListingPairBo>();
        ir.setRowNumber(rowNumber);
        ir.setRow(row);
        if (SheetUtils.isAllFieldsEmpty(row)) {
            ir.setEmptyRow(true);
            ir.addError("", "空行");
            return ir;
        }
        final Set<ConstraintViolation<ListingPairBo>> validate = validator.validate(row);
        boolean isOutputVo = vo != null;
        if (!isOutputVo) {
            vo = new ListingPairBo();
        }
        BeanUtils.copyProperties(row, vo);
        // 收集基本校验错误
        ir.initErrors(validate, ListingPairBo.class);

        vo.setIsSync(SheetUtils.tryToBoolean(row.getSyncImg()));

        return ir;
    }

    /**
     * 批量保存
     *
     * @param params
     * @return
     */
    public boolean batchPair(List<ListingPairBo> params) {
        List<ListingFather> list = new ArrayList<>();
        List<Product> productList = new ArrayList<>();
        for (ListingPairBo listingPair : params) {

            if (!StringUtils.hasText(listingPair.getMsku())
                    || !StringUtils.hasText(listingPair.getSku())) {
                continue;
            }

            Product product = productService.getOne(Wrappers.lambdaQuery(Product.class).eq(Product::getSku, listingPair.getSku()));

            LambdaQueryWrapper<ListingFather> queryWrapper = Wrappers.lambdaQuery(ListingFather.class).eq(ListingFather::getMsku, listingPair.getMsku());
            if (StringUtils.hasText(listingPair.getShopName())) {
                Long shopId = shopInfoService.getIdByShopName(listingPair.getShopName());
                queryWrapper.eq(ListingFather::getShop, shopId);

            }
            List<ListingFather> listingFathers = this.list(queryWrapper);

            listingFathers.stream().forEach(listingFather -> {
                listingFather.setPairProduct(product.getId());
                listingFather.setProductName(product.getName());
                listingFather.setSku(product.getSku());
                listingFather.setClassify(product.getClassify());
                listingFather.setBrand(product.getBrand());
                listingFather.setPairStatus("1");
                listingFather.setPairUpdateTime(new Date());
                listingFather.setPairType("1");
                list.add(listingFather);
                if (listingPair.getIsSync()) {
                    product.setPicUrl(listingFather.getImg());
                    productList.add(product);
                }
            });
        }
        if (CollectionUtils.isNotEmpty(productList)) {
            productService.updateBatchById(productList, 5000);
        }
        return this.updateBatchById(list, 5000);
    }

    /**
     * 设置负责人
     *
     * @param param
     * @return
     */
    @DataActivity(
            action = SysDataActivityAction.Other,
            message = "%s执行了设置负责人操作"
    )
    public boolean updatePrincipal(ListingPrincipalBo param) {
        List<ListingFather> list = new ArrayList<>();
        for (Long listingId : param.getListingIds()) {
            ListingFather listingFather = this.getById(listingId);
            listingFather.setPrincipal(param.getUserId());
            list.add(listingFather);
        }
        return this.updateBatchById(list);
    }

    @DataActivity(
            action = SysDataActivityAction.Other,
            message = "%s执行了导入设置负责人操作"
    )
    public boolean uploadPrincipal(SysFile sysFile) throws Exception {
//        SysFile sysFile = fileService.upload(file, null);
        try (InputStream in = fileService.read(sysFile)) {
            List<ImportRow<ListingPrincipalPo>> rows = new ArrayList<>();
            List<ListingPrincipalBo> list = new ArrayList<>();

            // 读取 Excel 到 rows
            EasyExcel
                    .read(in)
                    .useDefaultListener(false)
                    .registerReadListener(
                            new TemplateModelBuildEventListener<>(ListingPrincipalPo.class, null) {
                                @Override
                                public void invokeRow(ListingPrincipalPo row, AnalysisContext cxt) {
                                    ListingPrincipalBo vo = new ListingPrincipalBo();
                                    ImportRow<ListingPrincipalPo> ir = excelToImportRow(row, cxt.readRowHolder().getRowIndex(), vo);
                                    if (ir.isEmptyRow()) {
                                        return;
                                    }
                                    rows.add(ir);
                                    list.add(vo);
                                }
                            }
                    )
                    .sheet()
                    .doRead();

            return batchUpdatePrincipal(list);
        }
    }

    /**
     * 导入单行处理
     *
     * @param row       要导入的行
     * @param rowNumber 所在行号
     * @param vo        输出VO,可空
     * @return 导入行对象
     */
    protected ImportRow<ListingPrincipalPo> excelToImportRow(ListingPrincipalPo row, Integer rowNumber, ListingPrincipalBo vo) {
        ImportRow<ListingPrincipalPo> ir = new ImportRow<ListingPrincipalPo>();
        ir.setRowNumber(rowNumber);
        ir.setRow(row);
        if (SheetUtils.isAllFieldsEmpty(row)) {
            ir.setEmptyRow(true);
            ir.addError("", "空行");
            return ir;
        }
        final Set<ConstraintViolation<ListingPrincipalPo>> validate = validator.validate(row);
        boolean isOutputVo = vo != null;
        if (!isOutputVo) {
            vo = new ListingPrincipalBo();
        }
        // 收集基本校验错误
        ir.initErrors(validate, ListingPrincipalPo.class);

//        vo.setIsSync(SheetUtils.tryToBoolean(row.getSyncImg()));
        if (StringUtils.hasText(row.getShop())
                && StringUtils.hasText(row.getRegion())
                && StringUtils.hasText(row.getAsin())) {
            Long shopId = shopInfoService.getIdByShopName(row.getShop());
            Long regionId = sysRegionService.getIdByName(row.getRegion());

            ListingFather listingFather = this.getOne(Wrappers.lambdaQuery(ListingFather.class)
                    .eq(ListingFather::getShop, shopId)
                    .eq(ListingFather::getAsin, row.getAsin())
                    .eq(ListingFather::getRegion, regionId));
            List<Long> ids = new ArrayList<>();
            ids.add(listingFather.getId());
            vo.setListingIds(ids);
        }
        if (StringUtils.hasText(row.getUserName())) {
            //SysUser user = sysUserService.getOne(Wrappers.<SysUser>query().eq("name", row.getUserName()));
            List<Long> names = sysUserService.listObjs(Wrappers.<SysUser>query().in("name", StrUtil.split(row.getUserName(), ',')), s -> Convert.toLong(s));
            vo.setUserId(names);
        }
        return ir;
    }

    public boolean batchUpdatePrincipal(List<ListingPrincipalBo> list) {
        for (ListingPrincipalBo principalBo : list) {
            new LambdaUpdateChainWrapper<>(baseMapper)
                    .set(ListingFather::getPrincipal, principalBo.getUserId())
                    .eq(ListingFather::getId, principalBo.getListingIds().get(0))
                    .update();
        }
        return true;
    }

    /**
     * 编辑本地信息
     *
     * @param model
     */
    @DataActivity(
            action = SysDataActivityAction.Other,
            message = "%s执行了编辑本地信息操作"
    )
    public void updateLocal(ListingFatherVo model) {
        new LambdaUpdateChainWrapper<>(baseMapper)
                .set(ListingFather::getSaleDate, model.getSaleDate())
                .set(ListingFather::getProductRemark, model.getProductRemark())
                .eq(ListingFather::getId, model.getId())
                .update();
    }

    @DataActivity(
            action = SysDataActivityAction.Other,
            message = "%s执行了同步商品操作"
    )
    public void syncListingByShop(Long shopId) throws Exception {
        final ShopInfo shopInfo = shopInfoService.getById(shopId);
        Assert.notNull(shopInfo, "未找到店铺");
        tmpSyncListingService.syncListingByShop(shopInfo);
    }

    @DataActivity(
            action = SysDataActivityAction.Other,
            message = "%s执行了全部同步操作"
    )
    public void syncListing() throws Exception {
        tmpSyncListingService.syncListing();
    }
}
